using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;

namespace Glpt.Data
{
    /// <summary>
    /// 数据库连接抽象类
    /// </summary>
    public abstract class AbstractInterFace : IDisposable
    {
        /// <summary>
        /// 系统启动时的目录路径
        /// </summary>
        public static string StartupPath = "";
        private const string DebugFileName = "debug.log";   //记录系统日志文件
        /// <summary>
        /// 是否记录日志
        /// </summary>
        public static bool IsWriteLog = false;
        /// <summary>
        /// 等待命令执行的时间（以秒为单位）。0表示没限制。
        /// </summary>
        public int CommandTimeout = ParamSet.CommandTimeout;
        /// <summary>
        /// 线程命令集合
        /// </summary>
        private static Dictionary<object, DbCommand> SearchHostObjCommand = new Dictionary<object, DbCommand>();
        /// <summary>
        /// 线程数据集合
        /// </summary>
        private static Dictionary<object, DataTable> SearchHostObjDataTable = new Dictionary<object, DataTable>();

        private static object privateCommandLock = new object();
        /// <summary>
        /// LeftChar
        /// </summary>
        public static string PublicLeftChar = "";
        /// <summary>
        /// RightChar
        /// </summary>
        public static string PublicRightChar = "";
        //代理模式下的真实数据库
        public DbItem real_db = null;

        /// <summary>
        /// 解密方法
        /// </summary>
        /// <param name="txt">要解密的字符串</param>
        /// <returns>解密后字符串</returns>
        protected string ReplaceString(String txt)
        {
            return ReplaceString(txt, PublicLeftChar, PublicRightChar);
        }
        /// <summary>
        /// 解密方法
        /// </summary>
        /// <param name="txt">要解密的字符串</param>
        /// <param name="lchar">LeftChar</param>
        /// <param name="rchar">RightChar</param>
        /// <returns>解密后字符串</returns>
        public static string ReplaceString(string txt, string lchar, string rchar)
        {
            if (lchar.Length > 0 && rchar.Length > 0)
            {
                int ibegin = txt.IndexOf(lchar);
                int iend = txt.IndexOf(rchar);
                if (ibegin >= 0 && iend > ibegin)
                {
                    string val1 = txt.Substring(ibegin, iend - ibegin + rchar.Length);
                    CharCrypto crytp = new CharCrypto();
                    crytp.Init(lchar, rchar);
                    string val2 = crytp.Decrypt(val1);
                    txt = txt.Replace(val1, val2);
                }
            }
            return txt;
        }

        /// <summary>
        /// 添加执行命令
        /// </summary>
        /// <param name="searchHostObj">发起执行的主体对象</param>
        /// <param name="cmdsql">数据库命令对象</param>
        public static void AddCommand(object searchHostObj, DbCommand cmdsql)
        {
            AddCommand(searchHostObj, cmdsql, null);
        }
        /// <summary>
        /// 添加执行命令
        /// </summary>
        /// <param name="searchHostObj">发起执行的主体对象</param>
        /// <param name="cmdsql">数据库命令对象</param>
        /// <param name="dt">数据对象</param>
        public static void AddCommand(object searchHostObj, DbCommand cmdsql, DataTable dt)
        {
            lock (privateCommandLock)
            {
                if (searchHostObj != null && !SearchHostObjCommand.ContainsKey(searchHostObj))
                {
                    SearchHostObjCommand.Add(searchHostObj, cmdsql);
                    if (dt != null)
                        SearchHostObjDataTable.Add(searchHostObj, dt);
                }
            }
        }
        /// <summary>
        /// 获取查询数据集
        /// </summary>
        /// <param name="searchHostObj">发起执行的主体对象</param>
        /// <returns>数据对象</returns>
        public static DataTable GetSearchDataTable(object searchHostObj)
        {
            if (SearchHostObjDataTable.ContainsKey(searchHostObj))
                return SearchHostObjDataTable[searchHostObj];
            else
                return null;
        }

        /// <summary>
        /// 移除执行命令
        /// </summary>
        /// <param name="searchHostObj">发起执行的主体对象</param>
        public static void RemoveCommand(object searchHostObj)
        {
            lock (privateCommandLock)
            {
                if (searchHostObj != null && SearchHostObjCommand.ContainsKey(searchHostObj))
                {
                    SearchHostObjCommand.Remove(searchHostObj);
                    if (SearchHostObjDataTable.ContainsKey(searchHostObj))
                    {
                        SearchHostObjDataTable.Remove(searchHostObj);
                    }
                }
            }
        }

        /// <summary>
        /// 尝试取消执行
        /// </summary>
        /// <param name="searchHostObj">发起执行的主体对象</param>
        /// <returns>是否取消</returns>
        public static bool CancelCommand(object searchHostObj)
        {
            if (searchHostObj != null && SearchHostObjCommand.ContainsKey(searchHostObj))
            {
                SearchHostObjCommand[searchHostObj].Cancel();
                return true;
            }
            else
                return false;
        }


        private static object privateObjectLock = new object();

        /// <summary>
        /// 保存数据库命令日志
        /// </summary>
        /// <param name="cmdsql">数据库命令对象</param>
        public static void WriteLog(DbCommand cmdsql)
        {
            if (IsWriteLog)
            {
                StringBuilder sbuf = new StringBuilder();
                sbuf.AppendLine(DateTime.Now.ToString() + ":");
                sbuf.AppendLine(cmdsql.CommandText);
                for (int i = 0; i < cmdsql.Parameters.Count; i++)
                {
                    sbuf.Append(cmdsql.Parameters[i].ParameterName + "=");
                    if (cmdsql.Parameters[i].Direction.Equals(ParameterDirection.Output))
                        sbuf.AppendLine("?");
                    else if (cmdsql.Parameters[i].Value != null)
                        sbuf.AppendLine(cmdsql.Parameters[i].Value.ToString());
                }
                lock (privateObjectLock)
                {
                    System.IO.File.AppendAllText(StartupPath + DebugFileName, sbuf.ToString());
                }
            }
        }
        private static object GuidObjectLock = new object();
        public static string GetGuidString()
        {
            return GetGuidString(32);
        }
        /// <summary>
        /// 获取唯一编码
        /// </summary>
        /// <param name="length">长度 32:Guid 17:yyyyMMddhhmmssfff 15:Ticks或其他</param>
        /// <returns>编码字符串</returns>
        public static string GetGuidString(int length)
        {
            if (length <= 0 || length >= 32)
                return Guid.NewGuid().ToString("N");
            else
            {
                lock (GuidObjectLock)
                {
                    System.Threading.Thread.Sleep(1);
                    DateTime dt = DateTime.Now;
                    if (length == 17)
                        return dt.ToString("yyyyMMddhhmmssfff");
                    else
                    {
                        string result = "";
                        if (length == 15)
                            result = dt.AddYears(2 - dt.Year).Ticks.ToString();
                        else
                            result = (dt.Ticks % ((long)Math.Pow(10, length))).ToString();
                        while (result.Length < length)
                        {
                            result = "0" + result;
                        }
                        return result;
                    }
                }
            }
        }
        /// <summary>
        /// 描述列元数据的DataTable
        /// </summary>
        public abstract DataTable SchemaTable { get; }
        /// <summary>
        /// 参数字符标志
        /// </summary>
        public abstract string ParamChar { get; }

        /// <summary>
        /// 函数字符标志
        /// </summary>
        public abstract string FunctionChar { get; }

        /// <summary>
        /// 字符串连接标志
        /// </summary>
        public abstract string ConcatChar { get; }

        /// <summary>
        /// 字段左字符
        /// </summary>
        public abstract string ColumnLeftChar { get; }

        /// <summary>
        /// 字段右字符
        /// </summary>
        public abstract string ColumnRightChar { get; }

        /// <summary>
        /// 是否有数据库事务
        /// </summary>
        /// <returns>是否</returns>
        public abstract bool HasTransaction();

        /// <summary>
        /// 开始数据库事务
        /// </summary>
        /// <returns>是否成功</returns>
        public abstract bool BeginTransaction();

        /// <summary>
        /// 提交数据库事务
        /// </summary>
        public abstract void Commit();

        /// <summary>
        /// 从挂起状态回滚事务
        /// </summary>
        public abstract void Rollback();

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>结果集</returns>
        public abstract DataTable ExecSelect(string sql);

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <returns>结果集</returns>
        public abstract DataTable ExecSelect(string sql, DbParamCollection sql_params);

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <param name="is_pro">是否是存储过程</param>
        /// <returns>结果集</returns>
        public abstract DataTable ExecSelect(string sql, DbParamCollection sql_params, bool is_pro);

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="searchHostObj">发起执行的主体对象</param>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <param name="is_pro">是否是存储过程</param>
        /// <param name="pageIndex">页码，从0开始，-1表示全部</param>
        /// <returns>结果集</returns>
        public abstract DataTable ExecSelect(object searchHostObj, string sql, DbParamCollection sql_params, bool is_pro, int pageIndex);

        /// <summary>
        /// 批量加载数据
        /// </summary>
        /// <param name="tablename">表名</param>
        /// <param name="map_mode">字段映射 0按名称 1按顺序</param>
        /// <param name="reader">数据流</param>
        /// <param name="batchsize">每一批次中的行数</param>
        public abstract void BulkCopy(string tablename, string map_mode, IDataReader reader, int batchsize);

        /// <summary>
        /// 批量加载数据
        /// </summary>
        /// <param name="tablename">表名</param>
        /// <param name="map_mode">字段映射 0按名称 1按顺序</param>
        /// <param name="table">数据表</param>
        /// <param name="batchsize">每一批次中的行数</param>
        public abstract void BulkCopy(string tablename, string map_mode, DataTable table, int batchsize);

        /// <summary>
        /// 批量加载数据
        /// </summary>
        /// <param name="tablename">表名</param>
        /// <param name="map_mode">字段映射 0按名称 1按顺序</param>
        /// <param name="rows">数据行</param>
        /// <param name="batchsize">每一批次中的行数</param>
        public abstract void BulkCopy(string tablename, string map_mode, DataRow[] rows, int batchsize);

        /// <summary>
        /// 获取数据流
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>数据流</returns>
        public abstract IDataReader ExecReader(string sql);

        /// <summary>
        /// 获取数据流
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <returns>数据流</returns>
        public abstract IDataReader ExecReader(string sql, DbParamCollection sql_params);

        /// <summary>
        /// 获取数据流
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <param name="is_pro">是否是存储过程</param>
        /// <returns>数据流</returns>
        public abstract IDataReader ExecReader(string sql, DbParamCollection sql_params, bool is_pro);

        /// <summary>
        /// 执行SQL命令
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <returns>结果集</returns>
        public abstract int ExecUpdate(string sql);

        /// <summary>
        /// 执行SQL命令
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <returns>结果集</returns>
        public abstract int ExecUpdate(string sql, DbParamCollection sql_params);

        /// <summary>
        /// 执行SQL命令
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <param name="is_pro">是否是存储过程</param>
        /// <returns>结果集</returns>
        public abstract int ExecUpdate(string sql, DbParamCollection sql_params, bool is_pro);

        /// <summary>
        /// 执行SQL命令
        /// </summary>
        /// <param name="searchHostObj">发起执行的主体对象</param>
        /// <param name="sql">SQL语句</param>
        /// <param name="sql_params">SQL参数列表</param>
        /// <param name="is_pro">是否是存储过程</param>
        /// <returns>结果集</returns>
        public abstract int ExecUpdate(object searchHostObj, string sql, DbParamCollection sql_params, bool is_pro);

        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务
        /// </summary>
        public abstract void Dispose();
    }
}
